Rather than modify the version of
RenderingEngine2.cpp from HelloArrow, it will be more
instructive if we can start our ES 2.0 backend by copying the contents of
RenderingEngine1.cpp over
whatever is already in RenderingEngine2.cpp, with two
exceptions: you’ll need to save the BuildShader and
BuildProgram methods from the existing
RenderingEngine2.cpp from HelloArrow, so copy them
somewhere safe for the moment. If you’re following along, do that now, and
then you’ll be ready to make some changes to the file. Example 1 shows the top part of
RenderingEngine2.cpp. New and changed lines are shown
in bold. Some sections of unchanged code are shown as
..., so don’t copy this over the existing code in its
entirety (just make the changes and additions shown in bold).Example 1. RenderingEngine2 class declaration
#include <OpenGLES/ES2/gl.h> #include <OpenGLES/ES2/glext.h> #include "IRenderingEngine.hpp" #include "Quaternion.hpp" #include <vector> #include <iostream>
#define STRINGIFY(A) #A #include "../Shaders/Simple.vert" #include "../Shaders/Simple.frag"
static const float AnimationDuration = 0.25f;
...
class RenderingEngine2 : public IRenderingEngine { public: RenderingEngine2(); void Initialize(int width, int height); void Render() const; void UpdateAnimation(float timeStep); void OnRotate(DeviceOrientation newOrientation); private: GLuint BuildShader(const char* source, GLenum shaderType) const; GLuint BuildProgram(const char* vShader, const char* fShader) const; vector<Vertex> m_cone; vector<Vertex> m_disk; Animation m_animation; GLuint m_simpleProgram; GLuint m_framebuffer; GLuint m_colorRenderbuffer; GLuint m_depthRenderbuffer; };
|
The Initialize method almost
stays as is, but this bit is no longer valid:
glMatrixMode(GL_PROJECTION);
glFrustumf(-1.6f, 1.6, -2.4, 2.4, 5, 10);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0, 0, -7);
For ES 2.0, this changes to the
following:
m_simpleProgram = BuildProgram(SimpleVertexShader,
SimpleFragmentShader);
glUseProgram(m_simpleProgram);
// Set the projection matrix.
GLint projectionUniform = glGetUniformLocation(m_simpleProgram,
"Projection");
mat4 projectionMatrix = mat4::Frustum(-1.6f, 1.6, -2.4, 2.4, 5, 10);
glUniformMatrix4fv(projectionUniform, 1, 0,
projectionMatrix.Pointer());
The BuildShader and
BuildProgram methods are the same as they were for the
ES 2.0 version of HelloArrow; no need to list them here. The shaders
themselves are also the same as HelloArrow’s shaders; remember, the
lighting is “baked,” so simply passing through the colors is
sufficient.
We set up the model-view within the
Render method, as shown in Example 2. Remember,
glUniformMatrix4fv plays a role similar to the
glLoadMatrix function in ES 1.1.
Example 2. RenderingEngine2::Render
void RenderingEngine2::Render() const { GLuint positionSlot = glGetAttribLocation(m_simpleProgram, "Position"); GLuint colorSlot = glGetAttribLocation(m_simpleProgram, "SourceColor");
glClearColor(0.5f, 0.5f, 0.5f, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnableVertexAttribArray(positionSlot); glEnableVertexAttribArray(colorSlot); mat4 rotation(m_animation.Current.ToMatrix()); mat4 translation = mat4::Translate(0, 0, -7);
// Set the model-view matrix. GLint modelviewUniform = glGetUniformLocation(m_simpleProgram, "Modelview"); mat4 modelviewMatrix = rotation * translation; glUniformMatrix4fv(modelviewUniform, 1, 0, modelviewMatrix.Pointer()); // Draw the cone. { GLsizei stride = sizeof(Vertex); const GLvoid* pCoords = &m_cone[0].Position.x; const GLvoid* pColors = &m_cone[0].Color.x; glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, pCoords); glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors); glDrawArrays(GL_TRIANGLE_STRIP, 0, m_cone.size()); } // Draw the disk that caps off the base of the cone. { GLsizei stride = sizeof(Vertex); const GLvoid* pCoords = &m_disk[0].Position.x; const GLvoid* pColors = &m_disk[0].Color.x; glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, pCoords); glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors); glDrawArrays(GL_TRIANGLE_FAN, 0, m_disk.size()); } glDisableVertexAttribArray(positionSlot); glDisableVertexAttribArray(colorSlot); }
|
Next, go through the file, and change any
remaining occurrences of RenderingEngine1 to
RenderingEngine2, including the factory method (and be
sure to change the name of that method to
CreateRenderer2). You also need to remove any
occurrences of _OES and OES. Now,
turn off the ForceES1 switch in
GLView.mm; this completes the changes required for
the shader-based version of HelloCone. It may seem silly to have added an
ES 2.0 renderer without having added any cool shader effects, but it
illustrates the differences between the two APIs.